import type {
  CreateConnector,
  WalletDetailsParams,
  WalletKitDetails,
  WalletKitWalletConnectParameters
} from '../types/Wallet'
import { walletConnect, type WalletConnectParameters } from '@wagmi/vue/connectors'
import { createConnector, type CreateConnectorFn } from '@wagmi/vue'

type GetWalletConnectConnectorParams = {
  projectId: string
  walletConnectParameters?: WalletKitWalletConnectParameters
}

type CreateWalletConnectConnectorParams = {
  projectId: string
  walletDetails: WalletDetailsParams
  walletConnectParameters?: WalletKitWalletConnectParameters
}

type GetOrCreateWalletConnectInstanceParams = {
  projectId: string
  walletConnectParameters?: WalletKitWalletConnectParameters
  nkDetailsShowQrModal?: WalletKitDetails['showQrModal']
}

/**
 * 创建walletConnect实例map防止定义多个相同的walletConnect实例
 */
const walletConnectInstances = new Map<string, ReturnType<typeof walletConnect>>()

/**
 * 创建或者获取一个walletconnect实例对象
 * @param projectId
 * @param walletConnectParameters
 * @param nkDetailsShowQrModal
 */
const getOrCreateWalletConnectInstance = ({
  projectId,
  walletConnectParameters,
  nkDetailsShowQrModal
}: GetOrCreateWalletConnectInstanceParams): ReturnType<typeof walletConnect> => {
  let config: WalletConnectParameters = {
    ...(walletConnectParameters ? walletConnectParameters : {}),
    projectId,
    showQrModal: false // 这个值是必填的值，否则，WalletConnect 弹窗 （Web3Modal） 将在连接钱包时弹出默认扫码框
  }
  // 如果用户需要这个默认的扫码弹窗可以传入nkDetailsShowQrModal为true来启用这个弹窗
  if (nkDetailsShowQrModal) {
    config = { ...config, showQrModal: true }
  }

  // 序列化配置作为map中搜索的key，看是否已经定义过该walletConnect实例，如果有就返回该连接器
  const serializedConfig = JSON.stringify(config)
  const sharedWalletConnector = walletConnectInstances.get(serializedConfig)
  if (sharedWalletConnector) {
    return sharedWalletConnector
  }

  // 创建一个新的walletConnect实例
  const newWalletConnectInstance = walletConnect(config)
  walletConnectInstances.set(serializedConfig, newWalletConnectInstance)
  return newWalletConnectInstance
}

/**
 * 创建一个基于walletConnect的连接器
 * @param projectId
 * @param walletDetails
 * @param walletConnectParameters
 */
function createWalletConnectConnector({
  projectId,
  walletDetails,
  walletConnectParameters
}: CreateWalletConnectConnectorParams): CreateConnectorFn {
  return createConnector((config) => ({
    ...getOrCreateWalletConnectInstance({
      projectId,
      walletConnectParameters,
      nkDetailsShowQrModal: walletDetails.nkDetails.showQrModal
    })(config),
    ...walletDetails
  }))
}

/**
 * 一个定义基于walletConnect的连接器的工厂函数
 * @param projectId
 * @param walletConnectParameters
 */
export function getWalletConnectConnector({
  projectId,
  walletConnectParameters
}: GetWalletConnectConnectorParams): CreateConnector {
  // 这边使用一下我们项目里面默认的projectId，给使用钱包工具的小伙伴提供一些便利
  const exampleProjectId = '21fef48091f12692cad574a6f7753643'

  if (!projectId || projectId === '') {
    throw new Error(
      '没有找到projectId。 现在，每个 dApp 都必须提供一个 WalletConnect Cloud projectId 才能启用 WalletConnect v2！！'
    )
  }

  if (projectId === 'YOUR_PROJECT_ID') {
    projectId = exampleProjectId
  }

  return (walletDetails: WalletDetailsParams) =>
    createWalletConnectConnector({
      projectId,
      walletDetails,
      walletConnectParameters
    })
}
